package com.lanhao.aot.nettyudp;

import java.net.InetSocketAddress;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;

public class UdpClient {
	private static Logger logger = LoggerFactory.getLogger(UdpClient.class);

	private int scanPort;
	
	public static AtomicReference<Set<String>> scanResult = new AtomicReference<>();

	static {
		scanResult.set(Sets.newHashSet());
	}

	public UdpClient(int scanPort) {
		this.scanPort = scanPort;
	}

	private static class CLientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
		@Override
		protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
			String mac = msg.content().toString(CharsetUtil.UTF_8);
			InetSocketAddress remoteAddress = msg.sender();
			String ip = remoteAddress.getAddress().getHostAddress();
			int port = remoteAddress.getPort();
			logger.info("搜索到结果mac={},ip={},port={}", mac, ip, port);
			scanResult.get().add(mac + "_" + ip);
			logger.info("扫描结果list={}", scanResult.get());
		}
	}

	public void scanGatewayDev() {
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true)
					.handler(new CLientHandler());

			Channel ch = b.bind(new InetSocketAddress("0.0.0.0", 0)).sync().channel();

			ch.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("AntGatewaySearch: Chicken Chicken, I'm Duck", CharsetUtil.UTF_8),
					new InetSocketAddress("255.255.255.255", scanPort))).sync();

			logger.info("scanGatewayDev......");
			// QuoteOfTheMomentClientHandler will close the DatagramChannel when a
			// response is received. If the channel is not closed within 5 seconds,
			// print an error message and quit.
			// 等待5秒钟
			if (!ch.closeFuture().await(5000)) {
				logger.info("Search request timed out.");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("Search, An Error Occur ==>" + e);
		} finally {
			group.shutdownGracefully();
		}
	}

	public static void main(String[] args) {
		UdpClient udpClient = new UdpClient(23401);
		while (true) {
			udpClient.scanGatewayDev();
		}
	}
}